package jmcnet.libcommun.socketpool
{
	import com.google.maps.controls.PositionControl;
	
	import flash.events.Event;
	import flash.events.EventDispatcher;
	import flash.events.IOErrorEvent;
	import flash.events.SecurityErrorEvent;
	import flash.events.TimerEvent;
	import flash.net.Socket;
	import flash.net.sendToURL;
	import flash.utils.Timer;
	
	import jmcnet.libcommun.logger.JMCNetLog4JLogger;
	
	import mx.collections.ArrayCollection;
	import mx.utils.ObjectUtil;

	/**
	 * The authenticated socket pool class permits to have a pool of generic socket which must be authenticated by external application before being usable.
	 * The principle is the following :
	 * - initialize it (with CTOR arguments or use default parameters) -> this sends a EVENT_POOL_INITIALIZED event,
	 * - connect all socket in the pool by calling connect,
	 * - for each connected socket call the authenticate method given by caller,
	 * - caller must call the onAuthenticateOk method to declare that socket is ready to use. When the 1rst connection is ready, it sends a EVENT_POOL_CONNECTED event,
	 * - get a free socket by calling getFreeSocket. If one is available, it is returns. If not caller has to wait for an EVENT_FREE_SOCKET message. The socket can be retrieved by calling getFreeSocket,
	 * - release a used socket by calling releaseSocket
	 * - disconnect all socket of the pool by calling disconnect -> this sends a EVENT_POOL_DISCONNECTED event
	 */
	[Event(name=EVENT_POOL_INITIALIZED, type="jmcnet.libcommun.socketpool.EventPoolSocket")]
	[Event(name=EVENT_POOL_CONNECTED, type="jmcnet.libcommun.socketpool.EventPoolSocket")]
	[Event(name=EVENT_POOL_DISCONNECTED, type="jmcnet.libcommun.socketpool.EventPoolSocket")]
	[Event(name=EVENT_FREE_SOCKET, type="jmcnet.libcommun.socketpool.EventPoolSocket")]
	public class SocketPoolAuthenticated extends SocketPool
	{
		private static var log:JMCNetLog4JLogger = JMCNetLog4JLogger.getLogger(SocketPoolAuthenticated);
		
		public static const EVENT_POOL_INITIALIZED:String="poolInitialized";
		public static const EVENT_POOL_CONNECTED:String="poolConnected";
		public static const EVENT_POOL_DISCONNECTED:String="poolDisconnected";
		public static const EVENT_FREE_SOCKET:String="freeSocket";
		
		// The callback when a connection is established
		private var _authenticateCallback:Function = null;
		
		public function SocketPoolAuthenticated(min:int=0, max:int=100, timeoutMs:uint=10000) {
			super(min, max, timeoutMs);
		}
		
		override public function connect(hostname:String, port:int, authenticateCallback:Function=null):void {
			if (logSocketPool) log.info("connect connecting to '"+hostname+":"+port+" authenticateCallback="+authenticateCallback);
			super.connect(hostname, port, null);
			_authenticateCallback = authenticateCallback;
		}
		
		override protected function onSocketOpen(event:Event):void {
			// The socket is now open, remove it from _inCreation and put it into _free
			var socket:TimedSocket = event.target as TimedSocket;
			
			if (logSocketPool) log.evt("The socket #"+socket.id+" is connected with MongoDB. Let's do authentication if needed");
			
			// If there is a callback, call it (after putting socket in freeSocket)
			if (_authenticateCallback != null) {
				if (logSocketPool) log.debug("Call to authenticateCallback");
				_authenticateCallback(socket);
			}
			// If there is no authenticateCallback add directly the socket in free list
			else {
				addSocketInFreeList(socket);
			}
		}
		
		public function onAuthenticateOk(socket:TimedSocket):void {
			if (logSocketPool) log.info("Calling onAuthenticateOk socket #"+socket.id);
			addSocketInFreeList(socket);
		}		
	}
}